function results = doProcess_dev(in)

  % TODO: refactor so that begin/end cast determination takes place before
  % conversion of non-pressure data, and use that to reduce # of dataLines
  % so that only down/up casts are converted for non-pressure data
  
    global currentCastGUIDs DB instHeaderData mSB
    global FlightRaw CastRaw isReleaseVer
    global P T C H X F U R dov S D OS O W UTCNOW
    
    try        
    now = UTCNOW; % Get current UTC time for AnalyzedDatetime field
    
  % Create Result Insert object for later use
    dataStruct = struct('SiteID', {[]},...
                        'SiteVisitRawGUID', {''},...
                        'CastRawGUID', {''},...
                        'ActualDepthDecimal', {[]},...
                        'ResultVoltage', {[]},...
                        'ResultDecimal', {[]},...
                        'ParameterID', {[]},... 
                        'EquipmentID', {[]},...
                        'Downcast', {[]},...
                        'MatlabDatetime', {[]},... 
                        'UTCDatetime', {''},...
                        'AnalyzedDatetime', {''},...
                        'UserCode', {''},...
...                        'DataProcCode', {[]},...
                        'DataQualityCode', {[]},... 
                        'DataQualityFlagCode', {''},...
                        'DataQualityControlLevelCode', {[]},...
                        'BinSampleSize', {[]});
    cols = fieldnames(dataStruct);
    I = Insert_dev(DB, struct('tbls', {{'Result'}}, 'cols', {cols}));
    if ~isempty(I.errCode)
        results = ['FATAL ERROR: Failed making Result Table insertion '...
                  'object; aborting.  '];
        return
    end
    
  % Create FlightRaw Update object for later use
    uF = Update_dev(DB, struct('tbls', {{FlightRaw}}));
    if ~isempty(uF.errCode)
        results = ['FATAL ERROR: Failed making FlightRaw Table insertion '...
                  'object; aborting.  '];
        return
    end

  % Which flights are in play?
    flightsInPlay = unique(in.FlightGUID);
    N = numel(flightsInPlay);
  % Initialize results structure
    results = struct([]);
    
  % Now, for each flight 
    for n=1:N
      % Indices of records (casts) in play with FlightGUID == flight
        allCasts = find(strcmp(flightsInPlay{n}, in.FlightGUID));
      % To speed up development testing, in each flight...
        if ~isReleaseVer() % ...if _dev version...
            allCasts = allCasts(1); % ...only process first cast...
        elseif ~isdeployed && ... % ...else if not deployed...
               numel(allCasts) > 3
            allCasts = allCasts(1:3); % ...process not more than 3 casts.
        end
        currentCastGUIDs = in.CastGUID(allCasts);

        flight = flightsInPlay{n};
        flightWhere = ['FlightGUID=''' flight ''''];
        if ~isdeployed
            disp([flightWhere ', processing # ' num2str(n)])
        end
        results(n).FlightGUID = flight;
                
      % Delete any Results already extant for the casts "in play" and, 
      % if successful, add them to the list of casts to be processed 
      % (and note any for which deletion fails)
        nc = 0; cip = []; dataUncleared = [];
        results(n).Casts.CastGUID = {};
        for idx=allCasts'
            currentCastGUIDs = in.CastGUID(idx);
            stmt = ['DELETE FROM Result WHERE UserCode=''MTLB'' AND '...
                    'CastRawGUID=''' in.CastGUID{idx} ''''];
            curs = exec(DB.DB, stmt);
            if isempty(curs.Message)
                commit(DB.DB);
                results(n).Casts.CastGUID{end+1} = in.CastGUID{idx};
                cip(end+1) = idx;
                nc = nc + 1;
                saveLog_dev('Old results cleared.  ', '', 'LF')
            else
                rollback(DB.DB)
                dataUncleared(end+1) = idx;
                saveLog_dev(['ALERT: deletion of this cast''s old data '...
                             'failed with error: ' curs.Message(1:end-1) ...
                             '; skipping to next cast.  '], '', 'LF')
            end
            close(curs)
        end
        currentCastGUIDs = in.CastGUID(setdiff(allCasts, cip));
        clear('curs');
        if ~isempty(dataUncleared)
            if ~nc % If no current CastGUID's old data was successfully cleared
              % log that result and ...
                saveLog_dev(['ALERT: failed clearing old data for all casts '...
                      'corresponding to FlightGUID ' flight '; this is a '...
                      '"fatal" error for that flight; continuing on to next '...
                      'flight.  ']);%, '', 'DB');                
              % ...skip to the next flight
                continue
            else                
                msg = ['ALERT: failed to clear old data from CastGUID '...
                       in.CastGUID{dataUncleared(1)}];
                if numel(dataUncleared) > 1
                    msg = [strrep(msg, 'GUID', 'GUID''s') sprintf(', %s',...
                           in.CastGUID{dataUncleared(2:end)}) '; skipped '...
                           'processing those casts.  '];
                else
                    msg = [msg '; skipped processing that cast.  '];
                end
                saveLog_dev(msg, '', 'DB')
            end
        end
        currentCastGUIDs = in.CastGUID(cip);
        results(n).Casts.CastBegI = zeros(nc,1); % These two enable on-the-fly
        results(n).Casts.CastEndI = zeros(nc,1); % "Downcast" determination
        results(n).Casts.SiteID = zeros(nc,1);
        results(n).Casts.SiteVisitGUID = cell(nc,1);
        results(n).Casts.t = cell(nc,1); % = "MatlabDatetime"
        results(n).Casts.P = cell(nc,1);
        results(n).Casts.hexResults = cell(nc,1);
        results(n).Casts.Plots = cell(nc,1);
        results(n).Casts.Paths = cell(nc,1);
        
        cpo = zeros(nc,1);
        where = cell(nc,1);

      % Get the pressure threshold and minimum soak duration; these might 
      % be date dependent, but we can at least assume constant for all 
      % casts of a given flight
        hf = BLOB2file(regexprep(in.CTDHexFileBLOB{cip(1)}, '\n', '\t\t\t'),...
                       '.\temp.hex');
        if ~isempty(hf.err)
            saveLog_dev(['ALERT: File error "' hf.err{:} '" trying to write '...
                  'CastGUID ' in.CastGUID{cip(1)} '''s hex file blob to '...
                  'temp file during set-up for that cast''s flight; '...
                  'skipping to next flight.  '])
            continue
        end
      % The following is just to be able to query the DB correctly
        try
            hex = ParseRawSBE25Data_dev(hf.name);
            hex.parseInstHeader;
            P = Pressure_dev(hex.dataFilename);
            P.getDBdata(DB, 'P')
            Pthresh = P.DBdata.Pthreshold;
            soakDuration = P.DBdata.PsoakDuration; % in minutes
        catch ME
            saveLog_dev(['ALERT: retrieving pressure threshold & minimum '...
                     'soak duration for FlightGUID ' flight ' from DB '...
                     'failed with the following error: "' ME.message '"; '...
                     'using default values of 5m and 1 min, resp.  '])
            Pthresh = 5;
            soakDuration = 1; % in minutes
        end

      % Now, for each cleared cast
        for i=1:nc
          % The current index
            idx = cip(i);
            currentCastGUIDs = in.CastGUID(idx);
            results(n).Casts.CastGUID{i} = in.CastGUID{idx};
            results(n).Casts.SiteID(i) = in.SiteID{idx};
            results(n).Casts.SiteVisitGUID{i} = in.SiteVisitGUID{idx};
            where{i} = ['CastGUID=''' in.CastGUID{idx} '''']; % Update adds the WHERE
            if ~isdeployed
                disp(['Pre-processing ' where{i} ', seq. # ' num2str(i)])
                disp(['Elapsed time: ' num2str((utcnow()-UTCNOW)*24*60) ' min'])
            end

          % Write current HEX and CON File Blobs to files
            if i~=1 % if i==1, this was just done
                hf = BLOB2file(regexprep(in.CTDHexFileBLOB{idx}, '\n',...
                                         '\t\t\t'), '.\temp.hex');
                if ~isempty(hf.err)
                    saveLog_dev(['ALERT: File error "' hf.err{:} '" trying '...
                             'to write CastGUID ' in.CastGUID{idx} '''s '...
                             'hex file blob to temp file during first loop '...
                             'over flight ' flight '''s casts; skipping to '...
                             'next cast.  '])
                    continue
                end
            end

            cf = BLOB2file(regexprep(in.CONFileBLOB{idx}, '\n', '\t\t\t'),...
                           '.\temp.xmlcon');
            if ~isempty(cf.err)
                saveLog_dev(['ALERT: file error "' cf.err{:} '" trying to '...
                         'write CastGUID ' in.CastGUID{idx} '''s xmlcon '...
                         'file blob to temp file during first loop over '...
                         'flight ' flight '''s casts; skipping to next cast.  '])
                continue
            end

          % Create parsing object
            hex = ParseRawSBE25Data_dev(hf.name, cf.name);

          % Parse and convert hex to dec
            hex.parseInstHeader % Creates instHeaderData for hex
              % At this point, the temp and cond sensor serial numbers, 
              % from the hex file blob, are in instHeaderData
            hex.unpackConfigDat
              % At this point, all the calib data, from the CON file blob,
              % are in hex.Sensors.<type>Sensor.<parameterName>, except for
              % parameters w/ more than one possible claib. equation, e.g.,
              % conductivity and dissolved oxygen, so now we need to deal
              % w/ that
            fn = fieldnames(hex.Sensors)';
            for f = fn
                f = f{:};
                ffn = fieldnames(hex.Sensors.(f))';
                for ff = ffn
                    ff = ff{:};
                    if iscell(hex.Sensors.(f).(ff)) && ...
                       isstruct(hex.Sensors.(f).(ff){1})
                      % Note: the following is hardly robust because it 
                      % relies on Seabird demarcating their formula-use
                      % indicator w/ a tag that includes the string Use,
                      % but it must suffice for now
                        index = hex.Sensors.(f).(ffn{~cellfun(@isempty,...
                                                     strfind(ffn,'Use'))})...
                                                     + 1;
                        for fff = fieldnames(hex.Sensors.(f).(ff){index})'
                            fff = fff{:};
                            hex.Sensors.(f).(fff) = ...
                                hex.Sensors.(f).(ff){index}.(fff);
                        end
                        hex.Sensors.(f) = rmfield(hex.Sensors.(f), ff);
                    end
                end
            end
            if isempty(strfind(instHeaderData.dataOrig, in.HEXFileName{idx}))
                saveLog_dev(['ALERT: for CastGUID ' in.CastGUID{idx} ', '...
                         'hex file name mismatch between that recorded in '...
                         'the DB and that in the hex file blob itself.  '])
            end
            if (hex.Sensors.TemperatureSensor.SerialNumber~=instHeaderData.tempSN)
                saveLog_dev(['ALERT: temp sensor ser. # mismatch between '...
                         'CastGUID ' in.CastGUID{idx} '''s hex file and '...
                         'its xmlcon file; the xmlcon file value will be '...
                         'used in comparison with database value.  '])
            end
            if (hex.Sensors.ConductivitySensor.SerialNumber~=instHeaderData.condSN)
                saveLog_dev(['ALERT: conductivity sensor ser. # mismatch '...
                         'between CastGUID ' in.CastGUID{idx} '''s hex '...
                         'file and its xmlcon file; the xmlcon file value '...
                         'will be used in comparison with database value.  '])
            end
     %%%%%% This is where all the conversion action happens in this loop
            hex.convertHexData
     %%%%%% 
          % Done w/ temp files => delete them
            hf.deleteFile
            if hf.err{:}
                saveLog_dev(['ALERT: attempt to delete CastGUID '...
                         in.CastGUID{idx} '''s temporary hex file returned '...
                         'DOS file deletion error code ' num2str(hf.err{:}) ...
                         '; non-blocking, continuing with processing.  '])
            end
            cf.deleteFile
            if cf.err{:}
                saveLog_dev(['ALERT: attempt to delete CastGUID '...
                         in.CastGUID{idx} '''s temporary xmlcon file '...
                         'returned DOS file deletion error code '...
                         num2str(cf.err{:}) '; non-blocking, continuing '...
                         'with processing.  '])
            end
            
            if ~isdeployed
                disp([char(9) 'Input files processed'])
                disp(['Elapsed time: ' num2str((utcnow()-UTCNOW)*24*60) ' min'])
            end

            if i==1 % First time through for each flight
              % Get the sensor CCs
                stmt = 'varargout = {};';
                pList = {'P', 'T', 'C', 'O', 'H', 'X', 'F', 'U', 'R'};
                hex = getCCs_dev(hex, pList, in.FlightDatetime(idx),...
                                             in.FlightGUID(idx));
                if isempty(hex.Sensors)
                    currentCastGUIDs = in.CastGUID(cip);
                    saveLog_dev(['ALERT: calib. coef. query for FlightGUID '...
                          flight ' returned no data; skipping to next '...
                          'flight.  '])
                    currentCastGUIDs = in.CastGUID(idx);
                    break
                end
            else % otherwise, use the CCs obtained the first time through
                hex.Sensors = results(n).Casts.hexResults{1}.Sensors;
            end

          % Convert raw pressure signal to physical units
            results(n).Casts.P{i} = Pressure_dev(hex, DB);
            P = results(n).Casts.P{i}.outData;
            lastI = numel(P);

%           % Create time elapsed vector for this cast
%           % Will need regardless of QAQC do-ability
%             cast0 = myDotNetDateTime(instHeaderData.castDatetime);
%             t0 = cast0.MLBsdns;
%           % Now, first try to QAQC
%             warning('off', 'MATLAB:datenum:EmptyDate');
%             doQA = 1;
%             try
%                 refTD = myDotNetDateTime(combineDateAndTime(...
%                         in.FlightDatetime{idx}(1:10),...
%                         [in.TimeDown{idx}(1:2) ':' in.TimeDown{idx}(3:4)]));
%             catch ME
%                 doQA = 0;
%                 saveLog_dev(['ALERT: "' ME.message '" error trying to proc'...
%                          'ess TimeDown field for QAQC against hexfile head'...
%                          'er value, continuing without said QAQC.  '])
%             end
%             if doQA
%                 tmpQ = query_dev(DB, struct('tbls', {{'Global'}},...
%                                         'cols', {{'GlobalQuantity'}},...
%                                         'where', {{'GlobalTypeID=37'}}));
%                 if ~isempty(tmpQ.errCode)
%                     saveLog_dev(['ALERT: "' [tmpQ.errCode{:}] '" error returned '...
%                              'constructing DB query for beginning-of-cast toler'...
%                              'ance; proceeding with default value of 5 minutes.  '])
%                     TDtol = 5; % 5 minutes = default tolerance
%                 else
%                     tmpQ.submitStatement
%                     if ~isempty(tmpQ.errCode)
%                         saveLog_dev(['ALERT: "' [tmpQ.errCode{:}] '" error ret'...
%                                  'urned querying DB for beginning-of-cast toler'...
%                                  'ance; proceeding with default value of 5 '...
%                                  'minutes.  '])
%                         TDtol = 5; % 5 minutes = default tolerance
%                     else
%                         TDtol = tmpQ.result{:};
%                     end
%                 end
%               % Allow for DST
%                 if refTD.isDST
%                     reft = refTD.MLBsdns + 7/24;
%                 else
%                     reft = refTD.MLBsdns + 8/24;
%                 end
%                 if abs(t0-reft) > TDtol/60/24
%                     saveLog_dev(['ALERT: the difference between the flight app '...
%                              'record of the start time of CastGUID '...
%                              in.CastGUID{idx} ' and that recorded in this '
%                              'cast''s hexfile header exceeded the desired '...
%                              'tolerance of ' num2str(TDtol) 'minutes; this '...
%                              'alert is merely advisory, processing will con'...
%                              'tinue using the hexfile header value of '...
%                              datestr(t0) '.  '])
%                 end
%             end
%           % Now create the time elapsed vector
%             results(n).Casts.t{i} = t0 + (1:lastI)'/86400/ ... (86400 sec/dy)/scans per sec
%                                     instHeaderData.scanRate; 

          % Cast Pressure Offet defaults to last sampled pressure
            cpo(i) = P(lastI);

          % End of down-cast = beginning of upcast = index of maximum pressure
          % During development testing, an anomalous pressure maximum was 
          % encountered at the beginning of a dataset, thus the following
          % code to skip such "early" maxima 
            tmp = P;
            [maxP, EndI] = max(tmp);
            while EndI==1
                tmp = tmp(2:end);
                [maxP, EndI] = max(tmp);
            end
            results(n).Casts.CastEndI(i) = EndI;

          % for P( End(i):-1:(end of minimum soak) ), P < thresh
          % calculate derivative using six-point "Akima" spline formula
            soakEndIndex = floor(60*soakDuration*results(n).Casts.P{i}.scanRate);
            dcP = P(results(n).Casts.CastEndI(i):-1:soakEndIndex); 
            dcP(dcP >= Pthresh) = NaN;
            dP = (dcP(7:end) + dcP(6:end-1) + dcP(5:end-2) ...
                - dcP(3:end-4) - dcP(2:end-5) - dcP(1:end-6))/12;

          % Beg = index of: first derivitave value > 0;
          % or, if such doesn't exist, the last NaN value
            choose = (dP > 1e-6 * results(n).Casts.P{i}.SBEprec);
            if any(choose)
                BegI = EndI - find(choose, 1, 'first') + 1;
            else
                BegI = EndI - find(isnan(dcP), 1, 'last') + 1;
            end
            results(n).Casts.CastBegI(i) = BegI;

          % Plot the pressures, suitably annotated w/ above results
            figure('Visible', 'off');
            plot(P, 'b-');
            ylim = get(gca, 'YLim');
            range = max(ylim) - min(ylim);
            set(gca, 'Ylim', [min(ylim) - 0.1*range; max(ylim) + 0.1*range],...
                     'YDir', 'reverse')
            xlabel('Scan Number')
            ylabel('Unadjusted Pressure (db)')
            hold on;

            beginMark = plot(BegI, P(BegI), '+');
            set(beginMark, 'MarkerSize', 9, 'Color', [0 150/255 0])
            text(BegI, P(BegI) - 0.05*range,...
                 sprintf('(%d, %g)', [BegI P(BegI)]),...
                 'Color', [0 150/255 0], 'HorizontalAlignment', 'center')

            endMark = plot(EndI, P(EndI), 'r+');
            set(endMark, 'MarkerSize', 9)
            text(EndI, maxP + 0.05*range, sprintf('(%d, %g)',...
                [EndI P(EndI)]), 'Color', 'r',...
                'HorizontalAlignment', 'center')

            CPOmark = plot(lastI, P(lastI), 'k+');
            set(CPOmark, 'MarkerSize', 9)
            text(lastI, P(lastI) - 0.05*range, sprintf('(%d, %g)',...
                [lastI P(lastI)]), 'Color', 'k',...
                'HorizontalAlignment', 'right')

            title(['Pressure vs. Scan Number for Flight ' in.FlightDBName{idx}...
                   ', Site Code ' in.SiteCode{idx} ', Cast Number '...
                   num2str(in.CastNumber{idx}) char(10) 'with '... 
                   'Cast Pressure Offset and Downcast Begin and End '...
                   'Estimates Marked'],...
                   'Interpreter', 'none')

            if ~isempty(in.paths{idx})
              % Archive the figure as a MATLAB figure...
                fnroot = [regexprep(in.FlightDBName{idx}, ' ', '_')...
                          '_SiteCode_' in.SiteCode{idx}...
                          '_Cast_' num2str(in.CastNumber{idx})];
                fullPath = fullfile(in.paths{idx}, fnroot);
                hgsave(gcf, fullPath)
                set(gcf, 'InvertHardCopy', 'off');
                print(gcf, '-dpng', '-r150', fullPath);
                results(n).Casts.Plots{i} = fig2bin(gcf);
                results(n).Casts.Paths{i} = fullPath;
            else
                results(n).Casts.Paths{i} = ['Path didn''t exist and could'...
                                             'n''t be made'];
            end
            
          % Now get rid of the soak
            hex.dataLines = hex.dataLines(BegI:end);
            P = P(BegI:end);
            lastI = numel(P);
            results(n).Casts.P{i}.outData = P;
            hex.Pn = hex.Pn(BegI:end);
            hex.Tf = hex.Tf(BegI:end);
            hex.Cf = hex.Cf(BegI:end);
            hex.rV = hex.rV(BegI:end,:);
            results(n).Casts.hexResults{i} = hex;

          % Create time elapsed vector for this cast
          % Will need regardless of QAQC do-ability
            cast0 = myDotNetDateTime(instHeaderData.castDatetime);
            t0 = cast0.MLBsdns;
          % Now, first try to QAQC
            warning('off', 'MATLAB:datenum:EmptyDate');
            doQA = 1;
            try
                refTD = myDotNetDateTime(combineDateAndTime(...
                        in.FlightDatetime{idx}(1:10),...
                        [in.TimeDown{idx}(1:2) ':' in.TimeDown{idx}(3:4)]));
            catch ME
                doQA = 0;
                saveLog_dev(['ALERT: "' ME.message '" error trying to proc'...
                         'ess TimeDown field for QAQC against hexfile head'...
                         'er value, continuing without said QAQC.  '])
            end
            if doQA
                tmpQ = query_dev(DB, struct('tbls', {{'Global'}},...
                                        'cols', {{'GlobalQuantity'}},...
                                        'where', {{'GlobalTypeID=37'}}));
                if ~isempty(tmpQ.errCode)
                    saveLog_dev(['ALERT: "' [tmpQ.errCode{:}] '" error returned '...
                             'constructing DB query for beginning-of-cast toler'...
                             'ance; proceeding with default value of 5 minutes.  '])
                    TDtol = 5; % 5 minutes = default tolerance
                else
                    tmpQ.submitStatement
                    if ~isempty(tmpQ.errCode)
                        saveLog_dev(['ALERT: "' [tmpQ.errCode{:}] '" error ret'...
                                 'urned querying DB for beginning-of-cast toler'...
                                 'ance; proceeding with default value of 5 '...
                                 'minutes.  '])
                        TDtol = 5; % 5 minutes = default tolerance
                    else
                        TDtol = tmpQ.result{:};
                    end
                end
              % Allow for DST
                if refTD.isDST
                    reft = refTD.MLBsdns + 7/24;
                else
                    reft = refTD.MLBsdns + 8/24;
                end
                if abs(t0-reft) > TDtol/60/24
                    saveLog_dev(['ALERT: the difference between the flight app '...
                             'record of the start time of CastGUID '...
                             in.CastGUID{idx} ' and that recorded in this '...
                             'cast''s hexfile header exceeded the desired '...
                             'tolerance of ' num2str(TDtol) 'minutes; this '...
                             'alert is merely advisory, processing will con'...
                             'tinue using the hexfile header value of '...
                             datestr(t0) '.  '])
                end
            end
          % Now create the time elapsed vector
            results(n).Casts.t{i} = t0 + (1:lastI)'/86400/ ... (86400 sec/dy)/scans per sec
                                    instHeaderData.scanRate; 
          % Record cast success
            saveLog_dev(['Initial processing of cast ' in.CastGUID{idx} ...
                  ' successful.  ']);

        end % of first loop through one flight's casts
        
        if ~isdeployed
            disp(['Flight # ' num2str(n) ' pre-processed'])
        end
        
        currentCastGUIDs = in.CastGUID(cip);

        if isstruct(hex.Sensors)
          % Conditionally, assign and push flight DPO
            DPO = in.DailyPressOffset{cip(1)}; % DPO should be the same for
                                               % all casts from a given flight
            if isnan(DPO)
                DPO = median(cpo);
                uF.setPropVals('cols', {'DailyPressOffset'})
                uF.setPropVals('data', struct('DailyPressOffset', DPO))
                uF.setPropVals('where', {flightWhere})
                uF.submitStatement
            end
            results(n).DPO = DPO;

          % Update CastRaw
            data = struct('ScanNumBegin', {results(n).Casts.CastBegI},...
                          'ScanNumEnd', {results(n).Casts.CastEndI},...
                          'ScanNumFigBLOB', {results(n).Casts.Plots},...
                          'CastPressureOffset', {cpo},...
                          'ArchivedFigFileRoot', {results(n).Casts.Paths});
            uC = Update_dev(DB, struct('tbls', {{CastRaw}},...
                                       'cols', {{'ScanNumBegin', 'ScanNumEnd',...
                                                 'ScanNumFigBLOB', 'CastPressureOffset',...
                                                 'ArchivedFigFileRoot'}},...
                                       'data', {data}, 'where', {where}));
            uC.submitStatement

          % Update logs
          % TODO

          % Add DPO to pressures and process other parameters from hex files
          % Initialize storage
            results(n).Casts.A = cell(nc,1); % Attenuation
            results(n).Casts.B = cell(nc,1); % "Bad scan" indicator
            results(n).Casts.C = cell(nc,1); % Conductivity
            results(n).Casts.F = cell(nc,1); % Fluoresence/chlorophyl
            results(n).Casts.H = cell(nc,1); % pH
            results(n).Casts.O = cell(nc,1); % Dissolved oxygen
            results(n).Casts.Osat = cell(nc,1); % Oxygen saturation
            results(n).Casts.R = cell(nc,1); % PAR
            results(n).Casts.S = cell(nc,1); % Salinity
            results(n).Casts.sigmat = cell(nc,1); % Density
            results(n).Casts.T = cell(nc,1); % Temperature
            results(n).Casts.U = cell(nc,1); % Turbidity
            results(n).Casts.W = cell(nc,1); % Descent rate
            results(n).Casts.X = cell(nc,1); % Transmissivity
            results(n).Casts.Z = cell(nc,1); % Depth

          % Second loop through casts of a single flight
            for i=1:nc
                
                if ~isdeployed
                    disp([char(9) 'Processing cast # ' num2str(i)])
                    disp(['Elapsed time: ' num2str((utcnow()-UTCNOW)*24*60) ' min'])
                end
        
                idx = cip(i);
                currentCastGUIDs = in.CastGUID(idx);
                hexResults = results(n).Casts.hexResults{i};
                sz = [numel(hexResults.Pn) 1]; 
                allgood = ones(sz);
              % Add DPO to P  
                results(n).Casts.P{i}.outData = results(n).Casts.P{i}.outData ...
                                                + results(n).DPO;
                P = results(n).Casts.P{i};
              % Temperature
                T = Temperature_dev(hexResults, DB);
              % Conductivity
                C = Conductivity_dev(hexResults, DB, P.outData, T.outData);
              % pH
                H = pH_dev(hexResults, DB, T.outData);
              % Transmissivity
                X = Xmiss_dev(hexResults, DB);
                A = X.outData.Beam_c;
                X.outData = X.outData.Xmiss;
              % Fluorescence
                F = Fluor_dev(hexResults, DB);
              % Turbidity
                U = Turb_dev(hexResults, DB);
              % PAR
                R = PAR_dev(hexResults, DB);
              % Dissolved Oxygen Voltage
                dov = DOV_dev(hexResults, DB... 
    ...                          P.outData, % Include for hysteresis
                             );

                if ~isdeployed
                    disp([char(9) 'Pre-filtering complete'])
                    disp(['Elapsed time: ' num2str((utcnow()-UTCNOW)*24*60) ' min'])
                end
                
              % Note: in each of the below, "mSB mode"--rounding of both inputs 
              % and outputs--is handled "internally"
              % Filter
                Filt = Filter_dev(DB);
                for field=fields(Filt.outData)'
                    f = field{:};
                    eval([f '.outData = Filt.outData.' f ';'])
                end
              % Align
                Align = AlignCTD_dev(DB);
                for field=fields(Align.outData)'
                    f = field{:};
                    eval([f '.outData = Align.outData.' f ';'])
                end
              % CTM
                ctm = CTM_dev(DB);
                for field=fields(ctm.outData)'
                    f = field{:};
                    eval([f '.outData = ctm.outData.' f ';'])
                end
              % Loop Edit
              % First determine cast portion
                e = results(n).Casts.CastEndI(i) - ...
                    results(n).Casts.CastBegI(i);
%                dataStruct.Downcast = allgood;
%                dataStruct.Downcast(1:e) = 0;
                Downcast = allgood;
                Downcast(1:e) = 0;
                if mSB
                    in.Lat{idx} = 48;
                end
              % Now, do Loop Edit
              % Note: Loop Edit also calculates/returns our depth result,
              % so if/when a switch is added to enable turning LE off, 
              % do NOT implement it by skipping this call to LoopEdit
%                LE = LoopEdit_dev(DB, dataStruct.Downcast, P, in.Lat{idx});
                LE = LoopEdit_dev(DB, Downcast, P, in.Lat{idx});
                results(n).Casts.B{i} = LE.outData;
%                dataStruct.DataProcCode = LE.outData;
                DataProcCode = LE.outData;
              % Note: postpone rounding and reassigning depth result 'til after
              % full-window descent rate is calculated
                Z = LE.Z;
                if ischar(LE.W)
                    saveLog_dev(['Error in Loop Edit: its calculation of '...
                             'descent rate returned the following: ' LE.W ...
                             '.  ']);
                end

              % "Full-window" descent rate
                W = descentRate_dev(hexResults, DB, Z);
              % If in match SeaBird mode, round both Z and W to same prec. as P
                if mSB
                    Z = round2(Z, P.SBEprec); 
                    W.outData = round2(W.outData, P.SBEprec); 
                end
              % Now reassign Z
                results(n).Casts.Z{i} = Z;

              % Salinity
                S = Salinity_dev(hexResults, DB, P.outData, T.outData,...
                             C.outData);
              % Density
                D = Density_dev(hexResults, DB, S.outData, T.outData,...
                            P.outData);
              % OSat
                OS = DOS_dev(hexResults, DB, S.outData, T.outData);

              % DO
                O = DO_dev(hexResults, DB, T.outData, P.outData,...
                                           dov.outData, OS.outData);
                                       
              % Construct binning matrices, depth vector, etc.
                binStuff = cBinners_dev(Z, Downcast, DataProcCode);
                nRec = 2 * binStuff.N; allgood = ones(nRec,1);
                binner = binStuff.binner; ns = binStuff.ns;
                dataStruct.Downcast = [ones(binStuff.N,1);...
                                       zeros(binStuff.N,1)];
                dataStruct.ActualDepthDecimal = [binStuff.Z;...
                                                 flipud(binStuff.Z)];
                dataStruct.BinSampleSize = ns;

              % Get ready to push
                dataStruct.UserCode = constCellArr('MTLB', [nRec 1]);
                dataStruct.AnalyzedDatetime = constCellArr(datestr(now,...
                                                    'mm/dd/yyyy HH:MM:SS'),...
                                                    [nRec 1]);
                tmp = results(n).Casts.SiteID(i);
                dataStruct.SiteID = tmp(allgood);
                dataStruct.SiteVisitRawGUID = constCellArr(...
                                     results(n).Casts.SiteVisitGUID(i),...
                                     [nRec 1]);
                dataStruct.CastRawGUID = constCellArr(...
                                         results(n).Casts.CastGUID(i),...
                                         [nRec 1]);
                if isempty(results(n).Casts.t{i})
                    dataStruct = rmfield(dataStruct, 'MatlabDatetime');
                    dataStruct = rmfield(dataStruct, 'UTCDatetime');
                    I.cols = setdiff(I.cols, {'MatlabDatetime',...
                                              'UTCDatetime'});
                else
                    tmp = binStuff.binner * results(n).Casts.t{i};
                    dataStruct.MatlabDatetime = tmp ./ binStuff.ns;
                    dataStruct.UTCDatetime = datestr(dataStruct.MatlabDatetime,...
                                                     'mm/dd/yyyy HH:MM:SS.FFF');
                    I.cols = union(I.cols, {'MatlabDatetime', 'UTCDatetime'});
                end
              % These will have to move to change w/ each parameter eventually
    %             tmp = -1;
    %             dataStruct.DataQualityCode = tmp(allgood);
    %             dataStruct.DataQualityFlagCode = constCellArr('NA', sz);
    %             dataStruct.DataQualityControlLevelCode = tmp(allgood);

                if ~isdeployed
                    disp([char(9) 'Pre-push complete'])
                    disp(['Elapsed time: ' num2str((utcnow()-UTCNOW)*24*60) ' min'])
                end
                
              % Push the pressure results
                dataStruct.ResultVoltage = (binner * hexResults.Pn) ./ ns;
                I.setPropVals('data', dataStruct)
                P.outData = (binner * P.outData) ./ ns;
                results(n).Casts.P{i} = Push(P, I);

              % Temperature
                I.data.ResultVoltage = (binner * hexResults.Tf) ./ ns;
                T.outData = (binner * T.outData) ./ ns;
                results(n).Casts.T{i} = Push(T, I);

              % Conductivity
                I.data.ResultVoltage = (binner * hexResults.Cf) ./ ns;
                C.outData = (binner * C.outData) ./ ns;
                results(n).Casts.C{i} = Push(C, I);

              % DO
                I.data.ResultVoltage = (binner * hexResults.rV(:,...
                                  hexResults.Sensors.OxygenSensor.index-2))...
                                  ./ ns;
                O.outData = (binner * O.outData) ./ ns;
                results(n).Casts.O{i} = Push(O, I);

              % pH
                I.data.ResultVoltage = (binner * hexResults.rV(:,hexResults. ...
                                        Sensors.pH_Sensor.index-2)) ./ ns;
                H.outData = (binner * H.outData) ./ ns;
                results(n).Casts.H{i} = Push(H, I);

              % Transmissivity
                I.data.ResultVoltage = (binner * hexResults.rV(:,hexResults. ...
                    Sensors.TransChelseaSeatechWetlabCStarSensor.index-2)) ...
                    ./ ns;
                X.outData = (binner * X.outData) ./ ns;
                results(n).Casts.X{i} = Push(X, I);

              % Fluorescence
                I.data.ResultVoltage = (binner * hexResults.rV(:,hexResults. ...
                             Sensors.FluoroWetlabECO_AFL_FL_Sensor.index-2)) ...
                             ./ ns;
                F.outData = (binner * F.outData) ./ ns;
                results(n).Casts.F{i} = Push(F, I);

              % Turbidity
                I.data.ResultVoltage = (binner * hexResults.rV(:,hexResults. ...
                                     Sensors.UserPolynomialSensor.index-2)) ...
                                        ./ ns;
                U.outData = (binner * U.outData) ./ ns;
                results(n).Casts.U{i} = Push(U, I);

              % PAR
                I.data.ResultVoltage = (binner * hexResults.rV(:,hexResults. ...
                       Sensors.PAR_BiosphericalLicorChelseaSensor.index-2)) ...
                       ./ ns;
                R.outData = (binner * R.outData) ./ ns;
                results(n).Casts.R{i} = Push(R, I);

              % The rest don't have their own, distinct voltage signal
                I.data.ResultVoltage = NaN([nRec 1]);

              % Descent rate
                W.outData = (binner * W.outData) ./ ns;
                results(n).Casts.W{i} = Push(W, I);

              % Salinity
                S.outData = (binner * S.outData) ./ ns;
                results(n).Casts.S{i} = Push(S, I);

              % Density
                D.outData = (binner * D.outData) ./ ns;
                results(n).Casts.sigmat{i} = Push(D, I);

              % Oxygen saturation concentration
                OS.outData = (binner * OS.outData) ./ ns;
                results(n).Casts.Osat{i} = Push(OS, I);

              % Attenuation
                A = (binner * A) ./ ns;
                results(n).Casts.A{i} = Push(struct('outData', A,...
                                                    'ParamID', 50,... % 50 = atten's ParameterID
                                                    'EquipID', NaN), I);

            end % of second loop through one flight's casts
            saveLog_dev(['FlightGUID ' flight ' successfully processed.  '])
            if isdeployed % set FlightProcessed = 1
                uF.setPropVals('cols', {'Processed'})
                uF.setPropVals('data', struct('Processed', 1))
                uF.setPropVals('where', {flightWhere})
                uF.submitStatement
                if ~isempty(uF.errCode)
                    saveLog_dev(['ALERT: failure setting Processed = 1 for '...
                             'FlightGUID ' flight '.  '])
                    uF.errCode = {};
                end
            end
            results(n).time2ProcessFlight = utcnow()-now;
            now = now + results(n).time2ProcessFlight;
        end % of flights loop
    end
    
    catch ME
        results = getReport(ME);        
    end
    
end

function result = Push(var, I, varargin)%DQC, DQFC, DQCLC, allgood)
    global eN
    result = var.outData;
    sz = size(result);
    optargin = size(varargin, 2);

    if optargin < 4, allgood = ones(sz); else allgood = varargin{4}; end

    if optargin < 3, I.data.DataQualityControlLevelCode = -ones(sz); 
    else I.data.DataQualityControlLevelCode = varargin{3}; end

    if optargin < 2, I.data.DataQualityFlagCode = constCellArr('NA', sz); 
    else I.data.DataQualityFlagCode = varargin{2}; end
        
    if optargin < 1, I.data.DataQualityCode = -ones(sz); 
    else I.data.DataQualityCode = varargin{1}; end
        
    I.data.ParameterID = var.ParamID(allgood);
    I.data.EquipmentID = var.EquipID(allgood);
    I.data.ResultDecimal = result;
  % Final "scrub": change any Inf's to NaN's
    for f = fields(I.data)'
        tmp = I.data.(f{:});
        if isnumeric(tmp)
            tmp(~isfinite(tmp)) = NaN;            
        end
        I.data.(f{:}) = tmp;
    end
    I.submitStatement
    if ~isempty(I.errCode)
        saveLog_dev(['ALERT: "' regexprep([I.errCode{:}], char(10), ' ')...
                 '" error pushing ParameterID ' num2str(I.data.ParameterID...
                 (1)) ' for CastGUID ' I.data.CastRawGUID{1} '.  '])
        eN.send = 1;
        I.errCode = {};
    end
end